<--- %%NOBANNER%% --> GenReadMe.sas
 BackForward

/*-------------------<-- Start of Description-->---------------------\
| Generate a readme.doc file under the directory you specified;      |
| Note: the files must include the header using the format exactly   |
|       like this file;                                              |
|---------------------<-- End of Description-->----------------------|
|--------------------------------------------------------------------|
|-----------<-- Start of Files or Arguements Needed-->---------------|
| Arguments:                                                         |
|    directory  - the complete path to the directory you want to     |
|                 create your readme.doc file for;                   |
|    stopsign   - the end of the file header;                        |
|    outdata    - output dataset;                                    |
|    fextension - the type of files you want to create readme for;   |
|-----------------<-- End of Arguements Needed-->--------------------|
|--------------------------------------------------------------------|
|------------------<-- Start of Files Created-->---------------------|
| Example: %GenReadMe(directory=T:\TACHY\BIOSTAT\Duo\Projects\       |
|                     ACED-RID\DBget\ProgComp,outdata=dircnts);      |
| Usage:   %GenReadMe(directory=,stopsign='-----/', outdata=,       |
|           fextension='.sas');                                      |
\-------------------<-- End of Files Created-->---------------------*/
%macro GenReadMe(directory=,stopsign='-----*/', outdata=, fextension='.sas');
/*---------------------------------------------\
| Author:  Duo Zhou;                           |
| Created: 10-30-2001 10:46pm;                 |
| Purpose: Generate Readme Files under the     |
|          directory;                          |
\---------------------------------------------*/
/* The file assumes you have your file description listed in the file header */
/* the stopsign is the end of the file header. */
%local _tmplast_; %let _tmplast_=&syslast;
%let directory=%sysfunc(dequote(&directory));
%let fextension="%sysfunc(dequote(&fextension))";
%let stopsign="%sysfunc(dequote(&stopsign))";
%let olddir=&directory; 
%let output=&outdata;
%if (%length(%trim(%left(&directory))) >1) %then %do;
   %if (%quote(%substr(&directory, %length(&directory), 1)) ne %quote(\)) %then %do;
      %let directory=&directory.\;
   %end;
   %let ddir=%substr(&directory, 1, %eval(%length(&directory)-1));
%end;
%let dirrc=%sysfunc(filename(dirrf,&directory));
%let psid=%sysfunc(DOPEN(&dirrf));
%if &psid %then %do;
   %let today=%sysfunc(date(),mmddyy6.);
   %let dirrc=%sysfunc(DCLOSE(&psid));
   %let dirrc=%sysfunc(filename(dirrf));

   %dir(directory=&directory, outdata=_dirtmp);
   proc sort data=_dirtmp; by memname; run;
   /* Read In the files until the stopsign */
   DATA _tmp1;
      length fileloc myinfile $ 300 line $ 2000;
      set _dirtmp;
      by memname;
      line='';
      if index(memname, &fextension) then do;
         fileloc="&directory"||trim(left(memname));
           infile dummy length=linelen /*filename=myinfile line=lnum*/ end=done filevar=fileloc;
         do until(index(line, &stopsign) or done); 
              input @1 line $ varying2000. linelen;
            output;
         end;
      end;
   run;
   /* Keep one observation per row, and concatenate the file headers */
   /* into the file description.*/
   data _tmp2;
      set _tmp1;
      by memname;
      keep memname fDesBegRow fDesEndRow fHeaderBegRow fHeaderEndRow fParaBegRow fParaEndRow fLibBegRow 
           fLibEndrow fNeedBegRow fNeedEndrow fCreateBegRow fCreateEndrow fCommStartRow fCommEndRow;
      retain fDesBegRow fDesEndRow fNeedBegRow fNeedEndrow fCreateBegRow fCreateEndRow fHeaderBegRow 
             fHeaderEndRow fParaBegRow fParaEndRow fCommStartRow fCommEndRow fLibBegRow fLibEndrow;
      if first.memname then do;
         fDesBegRow=0; fDesEndRow=0; fNeedBegRow=0; fNeedEndrow=0; fCreateBegRow=0; fCreateEndRow=0;  
         fHeaderBegRow=0; fHeaderEndRow=0; fParaBegRow=0; fParaEndRow=0; fCommStartRow=0; fCommEndRow=0;
         fLibBegRow=0; fLibEndrow=0;
      end;
      if index(line, '<') and index(line, '>') and index(line, '--') and 
         index(upcase(compbl(line)), 'START OF') and index(upcase(compbl(line)), 'HEADER') 
         then  fHeaderBegRow =_n_+1;
      if index(line, '<') and index(line, '>') and index(line, '--') and 
         index(upcase(compbl(line)), 'END OF') and index(upcase(compbl(line)), 'HEADER') 
         then  fHeaderEndRow =_n_-1;
      if index(line, '<') and index(line, '>') and index(line, '--') and 
         index(upcase(compbl(line)), 'START OF') and index(upcase(line), 'PARAMETER') 
         then  fParaBegRow =_n_+1;
      if index(line, '<') and index(line, '>') and index(line, '--') and 
         index(upcase(compbl(line)), 'END OF') and index(upcase(line), 'PARAMETER') 
         then  fParaEndRow =_n_-1;
      if index(line, '<') and index(line, '>') and index(line, '--') and 
         index(upcase(compbl(line)), 'START OF') and (index(upcase(compbl(line)), 'DESCRIPTION') OR index(upcase(compbl(line)), 'PURPOSE')) 
         then fDesBegRow=_n_+1;
      if index(line, '<') and index(line, '>') and index(line, '--') and 
         index(upcase(compbl(line)), 'END OF') and 
         (index(upcase(compbl(line)), 'DESCRIPTION') OR index(upcase(compbl(line)), 'PURPOSE')) 
         then fDesEndRow=_n_-1;
      if index(line, '<') and index(line, '>') and index(line, '--') and 
         index(upcase(compbl(line)), 'START OF') and index(upcase(line), 'LIBRARY') 
         then fLibBegRow=_n_+1;
      if index(line, '<') and index(line, '>') and index(line, '--') and 
         index(upcase(compbl(line)), 'END OF') and index(upcase(line), 'LIBRARY') 
         then fLibEndrow=_n_-1;         
      if index(line, '<') and index(line, '>') and index(line, '--') and 
         index(upcase(compbl(line)), 'START OF') and index(upcase(compbl(line)), 'NEEDED') 
         then fNeedBegRow=_n_+1;
      if index(line, '<') and index(line, '>') and index(line, '--') and 
         index(upcase(compbl(line)), 'END OF') and index(upcase(compbl(line)), 'NEEDED') 
         then fNeedEndRow=_n_-1;
      if index(line, '<') and index(line, '>') and index(line, '--') and 
         index(upcase(compbl(line)), 'START OF') and 
         index(upcase(compbl(line)), 'CREATED') 
         then fCreateBegRow=_n_+1;
      if index(line, '<') and index(line, '>') and index(line, '--') and 
         index(upcase(compbl(line)), 'END OF') and 
         index(upcase(compbl(line)), 'CREATED') 
         then fCreateEndRow=_n_-1;
      if index(line, '<') and index(line, '>') and index(line, '--') and 
         index(upcase(compbl(line)), 'START OF') and 
         (index(upcase(compbl(line)), 'COMMENT') OR index(upcase(compbl(line)), 'NOTE') OR index(upcase(compbl(line)), 'EXAMPLE'))
         then  fcommStartRow =_n_+1;
      if index(line, '<') and index(line, '>') and index(line, '--') and 
         index(upcase(compbl(line)), 'END OF') and 
         (index(upcase(compbl(line)), 'COMMENT') OR index(upcase(compbl(line)), 'NOTE') OR index(upcase(compbl(line)), 'EXAMPLE'))
         then  fCommEndRow =_n_-1;
      if last.memname;
   run;
   data _tmp3;
      merge _tmp1 _tmp2;
      by memname;
      length fname $ 50 fHead fDes fPara fLib fNeed fCreate fComm $ 5000;
      retain fHead fDes fPara fLib fNeed fCreate fComm;
      fname=memname;
      if first.memname then do;
         fHead=''; fDes=''; fPara='';  fLib=''; fNeed=''; fCreate=''; fComm='';
      end;
      if not index(line, '-----') and not index(line, '=====') and 
         not index(line, '____') and not index(line, 'ŻŻŻŻ') and 
         not index(line, '<--') and not index(line, '>--') then do;
         line=tranwrd(line,'/*', ' ');
         line=tranwrd(line, '*/', ' ');
         line=compress(line, '|');
         line=compress(line, '*');
      end;
      if fHeaderBegRow<=_n_ and _n_<= fHeaderEndRow then fHead=compbl(fHead)||trimn(left(line));      
      if fDesBegRow<=_n_ and _n_<=fDesEndRow then fDes=compbl(fDes)||trimn(left(line));
      if fParaBegRow<=_n_ and _n_<= fParaEndRow then fPara=compbl(fPara)||trimn(left(line)); 
      if fLibBegRow<=_n_ and _n_<=fLibEndRow then fLib=compbl(fLib)||trimn(left(line));      
      if fNeedBegRow<=_n_ and _n_<=fNeedEndRow then fNeed=compbl(fNeed)||trimn(left(line));
      if fCreateBegRow<=_n_ and _n_<=fCreateEndRow then fCreate=compbl(fCreate)||trimn(left(line));
      if fCommStartRow<=_n_ and _n_<=fCommEndRow then fComm=compbl(fComm)||trimn(left(line));
      if last.memname;
      keep fname fsize fdatime fHead fDes fLib fNeed fCreate fPara fComm;
      label fname="File Name" fsize="File Size" fdatime="Last Modified Time" fHead="File Header" fDes="File Description" fPara="Parameter" fLib="Library" fNeed="Files or Datasets Needed" fCreate="Files Created" fComm="Comment, Reference or Usage";
   run;
   %if (%length(&output) gt 0) %then %do;
      /* Output a data set as &outdata*/
      data &output;
         set _tmp3;
      run;
   %end;
   /* Generate a Readme.doc file under the directory you provided*/
   %let readmetoday=%sysfunc(datetime(), datetime20.);
   %let readmedir=&ddir.\;
   options orientation=landscape;
   ods listing close;
   ods html file="&ddir.\_Readme.doc";
   ods path sasuser.templat(read);
   %let readmedir=&directory;
   %let readmetoday=%sysfunc(date(), mmddyy10.);
   data _null_;
      set _tmp3;
         file print ods = (
         template='base.readme'
            columns=(
            fname=fname(generic=on)
            fsize=fsize(generic=on)
            fdatime=fdatime(generic=on)
            fHead=fHead(generic=on)
            fDes=fDes(generic=on)
            fPara=fPara(generic=on)
            fLib=fLib(generic=on)
            fNeed=fNeed(generic=on)
            fCreate=fCreate(generic=on)
            fComm=fComm(generic=on)
            )
         );
     put _ods_;
   run;
/*   proc print data=_tmp3 label; */
/*   var fname fsize fdatime fHead fDes fLib fNeed fCreate fPara fComm; */
/*   title "Readme.doc For SAS Programs Under Directory: &directory.";*/
/*   run;*/
   ods path sashelp.tmplmst(read);
   ods html close;
   ods listing;
   options orientation=portrait;
   proc datasets library=work nolist;
        delete _tmp1 _tmp2 _tmp3 _dirtmp;
   run;quit;
%end;
%else %do;
   %put ==> Alert! I can%str(%')t find the directory;
   %put ==>        "&directory".;
%end; %let syslast=&_tmplast_;
%mend GenReadMe;